<template>
  <el-form-item ref="elFormItem" :label="itemParamsData.label" :prop="itemParamsData.prop" :label-width="itemParamsData.labelWidth" :size="autoSize">
    <!-- <template #slot:label>
      <span v-html="itemParamsData.label" />
    </template> -->
    <!-- 文本输入 -->
    <div v-if="orginInput.includes(itemParamsData.type)" :class="needFixedHeight()" :style="itemParamsData.style || {}" class="el-item">
      <el-input
        ref="itemConVm"
        v-model.trim="dataForm[itemParamsData.prop]"
        :class="{ 'inline-el': isInline }"
        :style="itemParamsData.style || {}"
        v-bind="itemParamsData"
        size="default"
        v-on="itemParamsData.events || {}"
      />
    </div>
    <div v-else-if="itemParamsData.type === 'textarea'" :class="needFixedHeight(true)" :style="itemParamsData.style || {}" class="el-item">
      <el-input
        ref="itemConVm"
        v-model="dataForm[itemParamsData.prop]"
        type="textarea"
        :style="itemParamsData.style || {}"
        v-bind="itemParamsData"
        v-on="itemParamsData.events || {}"
      />
    </div>
    <!-- 数字输入 -->
    <div
      v-else-if="itemParamsData.type === 'number'"
      :class="[isInline ? 'form-item-box__small' : 'not-inline-form-box']"
      :style="itemParamsData.style || {}"
    >
      <el-input-number
        ref="itemConVm"
        v-model.number="dataForm[itemParamsData.prop]"
        style="height: 100%; width: 100%; text-align: left"
        :min="itemParamsData.min || 0"
        :max="itemParamsData.max || Infinity"
        :precision="itemParamsData.precision || 2"
        :style="itemParamsData.style || {}"
        :step="itemParamsData.step || 1"
        :controls="itemParamsData.controls || true"
        v-bind="itemParamsData"
        v-on="itemParamsData.events || {}"
      />
    </div>
    <!-- 下拉选择 -->
    <div
      v-else-if="itemParamsData.type === 'select'"
      :class="[isInline ? 'form-item-box__small' : 'not-inline-form-box']"
      :style="itemParamsData.style || {}"
    >
      <el-select
        ref="itemConVm"
        v-model="dataForm[itemParamsData.prop]"
        v-bind="itemParamsData"
        :filterable="itemParamsData.filterable || false"
        style="height: 100%; width: 100%"
        size="big"
        :style="itemParamsData.style || {}"
        :class="{ 'inline-el': isInline }"
        v-on="itemParamsData.events || {}"
      >
        <el-option
          v-for="obj in itemParamsData.options || defOptions"
          :key="obj.value"
          :label="itemParamsData.labelKey ? obj[itemParamsData.labelKey] : obj.dispVal || obj.label"
          :value="itemParamsData.valueKey ? obj[itemParamsData.valueKey] : obj.dataVal || obj.value"
        />
      </el-select>
    </div>

    <!-- 下拉选择树 -->
    <div
      v-else-if="itemParamsData.type === 'tree'"
      :class="[isInline ? 'form-item-box__small' : 'not-inline-form-box']"
      :style="itemParamsData.style || {}"
    >
      <el-tree-select
        ref="itemConVm"
        v-model="dataForm[itemParamsData.prop]"
        v-bind="itemParamsData"
        :style="itemParamsData.style || {}"
        :class="{ 'inline-el': isInline }"
        :data="itemParamsData.options || defOptions"
        :render-after-expand="false"
        v-on="itemParamsData.events || {}"
      />
    </div>
    <!-- radio -->
    <div v-else-if="itemParamsData.type === 'radio'" :class="needFixedHeight()" :style="itemParamsData.style || {}">
      <el-radio-group ref="itemConVm" v-model="dataForm[itemParamsData.prop]" v-bind="itemParamsData" v-on="itemParamsData.events || {}">
        <el-radio
          v-for="obj in itemParamsData.options || defOptions"
          :key="itemParamsData.labelKey ? obj[itemParamsData.labelKey] : obj.label"
          :label="itemParamsData.labelKey ? obj[itemParamsData.labelKey] : obj.label"
          >{{ itemParamsData.nameKey ? obj[itemParamsData.nameKey] : obj.name }}</el-radio
        >
      </el-radio-group>
    </div>
    <!-- checkbox -->
    <div v-else-if="itemParamsData.type === 'checkbox'" :class="needFixedHeight()" :style="itemParamsData.style || {}">
      <el-checkbox-group ref="itemConVm" v-model="dataForm[itemParamsData.prop]" v-bind="itemParamsData" v-on="itemParamsData.events || {}">
        <el-checkbox
          v-for="obj in itemParamsData.options || defOptions"
          :key="itemParamsData.labelKey ? obj[itemParamsData.labelKey] : obj.label"
          :label="itemParamsData.labelKey ? obj[itemParamsData.labelKey] : obj.label"
          >{{ itemParamsData.nameKey ? obj[itemParamsData.nameKey] : obj.name }}</el-checkbox
        >
      </el-checkbox-group>
    </div>
    <!-- cascader 级联 -->
    <div
      v-else-if="itemParamsData.type === 'cascader'"
      :class="[isInline ? 'form-item-box__small' : 'not-inline-form-box']"
      :style="itemParamsData.style || {}"
    >
      <el-cascader
        ref="itemConVm"
        v-model="dataForm[itemParamsData.prop]"
        :style="itemParamsData.style || {}"
        :class="{ 'inline-el': isInline }"
        v-bind="itemParamsData"
        :options="itemParamsData.options || defOptions"
        no-data-text="暂无数据"
        v-on="itemParamsData.events || {}"
      />
    </div>
    <!-- date month year daterange datetime datetimerange monthrange -->
    <div v-else-if="dateType.includes(itemParamsData.type)" :class="needFixedHeight()" :style="itemParamsData.style || {}">
      <el-date-picker
        ref="itemConVm"
        v-model="dataForm[itemParamsData.prop]"
        :class="{ 'inline-el': isInline }"
        v-bind="itemParamsData"
        :picker-options="itemParamsData.pickerOptions || {}"
        :value-format="itemParamsData.valueFormat || 'YYYY-MM-DD'"
        style="height: 100%; width: 100%"
        v-on="itemParamsData.events || {}"
      />
    </div>
    <!-- 自动补全输入框  -->
    <div
      v-else-if="itemParamsData.type === 'autocomplete'"
      :class="[isInline ? 'form-item-box__small' : 'not-inline-form-box']"
      :style="itemParamsData.style || {}"
    >
      <el-autocomplete
        ref="itemConVm"
        v-model="dataForm[itemParamsData.prop]"
        :style="itemParamsData.style || {}"
        :class="{ 'inline-el': isInline }"
        v-bind="itemParamsData"
        :fetch-suggestions="querySearch"
        class="autocomplete"
        v-on="itemParamsData.events || {}"
        @focus="autoFocus(itemParamsData)"
      />
    </div>

    <!-- 上传 根据自己的项目来引用适用于自己项目的上传组件-->
    <div v-else-if="itemParamsData.type === 'file'" :class="needFixedHeight()" :style="itemParamsData.style || {}">
      <div>文件上传组件</div>
    </div>
    <!-- switch -->
    <div v-else-if="itemParamsData.type === 'switch'" :class="[isInline ? 'form-item-box__small' : 'not-inline-form-box']">
      <el-switch
        ref="itemConVm"
        v-model="dataForm[itemParamsData.prop]"
        :size="itemParamsData.size || 'large'"
        :disabled="itemParamsData.disabled || false"
        :active-text="dataForm[itemParamsData.prop] === (itemParamsData.activeVal || true) ? itemParamsData.activeText : itemParamsData.inactiveText"
        :active-value="itemParamsData.activeVal !== undefined ? itemParamsData.activeVal : true"
        :inactive-value="itemParamsData.inactiveVal !== undefined ? itemParamsData.inactiveVal : false"
        style="height: 100%"
        v-on="itemParamsData.events || {}"
      />
    </div>
    <!-- custom -->
    <div v-else-if="itemParamsData.type === 'custom'" :class="[needFixedHeight(), 'custom']" :style="itemParamsData.style || {}">
      <slot />
    </div>
    <div v-else-if="itemParamsData.type === 'render'" :class="needFixedHeight()" :style="itemParamsData.style || {}">
      <!-- 自定义渲染 -->
      <CustomRender v-model="dataForm[itemParamsData.prop]" :item="itemParamsData" />
    </div>
    <!-- 自定也组件引用 需要prop, componentName, folder or allPath -->
  </el-form-item>
</template>

<script setup>
import { computed, provide, inject, ref, reactive, onMounted, defineAsyncComponent, getCurrentInstance } from 'vue';
import CustomRender from './components/Render.vue';
import { dateType, orginInput, getPropByPath } from './itemDefCof.js';

// import dayjs from 'dayjs'
const props = defineProps({
  itemData: { type: Object, default: () => {} },
  formDatas: { type: Object, default: () => {} },
  // 是否是内联模式，非内联模式则会按照element的原型form一样，竖行排列
  isInline: { type: Boolean, default: true },
  // 校验信息 显示模式，正常element模式，另一种和宇云外部提示模式 type: eleMsg, outMsg
  validateMessageType: { type: String, default: 'eleMsg' },
  size: { type: String, default: 'small' } // 大小设置
});

//默认选项
const defOptions = reactive([
  { label: '选项1', value: '1' },
  { label: '选项2', value: '2' }
]);

provide('rootForm', {});
const dataForm = computed(() => {
  return props.formDatas;
});

// 自动计算 size
const autoSize = computed(() => {
  return props.size || props._elFormItemSize;
});

const rootForm = inject('rootForm');
const elForm = ref({});

// 默认配置项处理，如placeholder
const itemParamsData = computed(() => {
  const defParams = rootForm.itemDefCof[props.itemData.type] || {};
  const obj = Object.assign({}, defParams, props.itemData);
  if (props.validateMessageType === 'eleMsg') {
    if (!props.itemData.placeholder && defParams.placeholder) {
      obj.placeholder = defParams.placeholder + props.itemData.label.replace(/(：*$)|(:*$)/g, '');
    }
  } else {
    obj.placeholder = '';
    if (!isRequired()) {
      obj.messages = [];
      return obj;
    }
    if (!props.itemData.messages && !props.itemData.placeholder && defParams.placeholder) {
      obj.messages = [defParams.placeholder + props.itemData.label.replace(/(：*$)|(:*$)/g, '')];
    }
  }
  return obj;
});

const { proxy } = getCurrentInstance();
onMounted(() => {
  const itemConVm = ref(null);
  // item 内容初始化，回调，返回内容组件对象
  if (props.itemData.events && props.itemData.events.itemConVmInitFinish) {
    props.itemData.events.itemConVmInitFinish(itemConVm);
  }
});

//自动补全
const autoOptions = ref([]);
const querySearch = (queryString, cb) => {
  const results = queryString ? autoOptions.value.filter(createFilter(queryString)) : autoOptions.value;
  cb(results);
};
//选择过滤
const createFilter = (queryString) => {
  return (autoOptions) => {
    return autoOptions.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0;
  };
};
//配置选择
const autoFocus = (item) => {
  autoOptions.value = item.options;
};

/* 待处理内容
// else if (item.componentName) {
/* @vite-ignore */
//     const paths = '../FormItems/' + item.componentName + '/index.vue'
//     return import(paths)
// } else if (item.component) {
// // 直接传入组件的形式
//     return item.component
// }*/

// 动态添加样式
const needFixedHeight = () => {
  if (!props.isInline) {
    return 'not-inline-form-box';
  }
  if (props.itemData.span !== 24) {
    return 'form-item-box__small';
  }
  if (props.isGrid && props.itemData.xl !== 24) {
    return 'form-item-box__small';
  }
  return '';
};

// 获取校验规则
const getRules = () => {
  let formRules = elForm.value.rules || [];
  const prop = getPropByPath(formRules, props.itemData.prop || '');
  formRules = formRules ? prop.o[props.itemData.prop || ''] || prop.v : [];
  return [].concat(formRules || []);
};
// 是否必填
const isRequired = () => {
  const rules = getRules();
  let isRequired = false;
  if (rules && rules.length) {
    rules.every((rule) => {
      if (rule.required) {
        isRequired = true;
        return false;
      }
      return true;
    });
  }
  return isRequired;
};
</script>

<style lang="scss" scoped>
.form-item-box__medium {
  width: 100%;
  height: 36px;
  line-height: 36px;
  display: flex;
  align-items: center;
}

.form-item-box__small {
  width: 100%;
  height: 32px;
  line-height: 32px;
  display: flex;
  align-items: center;
}

.form-item-box__mini {
  width: 100%;
  height: 28px;
  line-height: 28px;
  display: flex;
  align-items: center;
}

.not-inline-form-box {
  display: inline-block;
}

.inline-el {
  width: 100%;
  height: 100%;
}

.tip-massage {
  padding: 3px 0;
  position: absolute;
  left: 0;
  top: 100%;
  font-size: 12px;
  color: #aaa;

  li {
    list-style-type: none;
    line-height: 16px;
  }
}

.is-error {
  .tip-massage {
    color: #ff7f52;
  }
}

:deep(.el-input__inner),
:deep(.el-textarea__inner) {
  // border-color: $border;

  &::-webkit-input-placeholder {
    color: #909399;
  }

  &:-moz-placeholder {
    color: #909399;
  }

  &::-moz-placeholder {
    color: #909399;
  }

  &:-ms-input-placeholder {
    color: #909399;
  }
}

:deep(.el-form-item__error) {
  padding: 3px;
  background-color: transparent;
  color: #ff7f52;
}

:deep(.el-radio) {
  &.is-checked {
    .el-radio__label {
      color: #384480;
    }

    .el-radio__inner {
      border-color: #384480;
      background-color: transparent;

      &::after {
        width: 8px;
        height: 8px;
        background-color: #384480;
      }
    }
  }
}

:deep(.el-checkbox) {
  &.is-checked {
    .el-checkbox__label {
      color: #384480;
    }

    .el-checkbox__inner {
      border-color: #384480;
      background-color: #384480;
    }
  }
}

:deep(.el-switch) {
  &.is-checked {
    .el-switch__core {
      border-color: #384480;
      background-color: #384480;
    }

    .el-switch__label.is-active {
      color: #384480;
    }
  }
}

.el-item {
  width: 100%;
}

:deep(.el-form-item__label) {
  height: 32px !important;
  line-height: 32px !important;
  font-size: 14px;
}

.custom {
  width: 100%;
}
</style>
